from ..extensions import marshmallow as ma
from  marshmallow import fields
from ..models.currency import Currency
from ..models.product import ProductCategory, Product

_default_error_messages = {
    'required': ' 不能为空'
}


def create_error_messages(**kwargs):
    kwargs.update(_default_error_messages)
    return kwargs


def _none_validator(data):
    return data is not None


def _email_validator(data):
    import re
    return re.match('^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$', data) is not None


def _amount_validator(data):
    if data < 0:
        return False


def _length_validator(length):
    def _length_validate(data):
        return len(data) > length

    return _length_validate


class CurrencyPostSchema(ma.Schema):
    currency = fields.Function(deserialize=lambda obj: Currency.get_or_none(Currency.id == obj))


class ProductCategorySchema(ma.Schema):
    product_category = fields.Function(deserialize=lambda obj: Currency.get_or_none(Currency.id == obj),
                                       load_from='category_id')


class CartItemAdditiveSchema(ma.Schema):
    type = fields.Str(required=True, error_messages=_default_error_messages)
    ref_id = fields.Str(required=True, error_messages=_default_error_messages)
    required = fields.Str()


class ShopCartItemSchema(ma.Schema):
    #  product = fields.Str(required=True, error_messages=_default_error_messages)
    additives = fields.List(fields.Nested(CartItemAdditiveSchema))
    id = fields.Int()
    member = fields.Str()
    count = fields.Int(required=True, error_messages=_default_error_messages)
    offer = fields.Int(required=True, error_messages=_default_error_messages)
    source = fields.Str(required=True, error_messages=_default_error_messages)


class ShopCartSchema(ma.Schema):
    # id = fields.Str(required=True, error_messages=_default_error_messages)
    items = fields.List(fields.Nested(ShopCartItemSchema), required=True, error_messages=_default_error_messages)


class LocalAuthSchema(ma.Schema):
    login_name = fields.Str(required=True, allow_none=False,
                            error_messages=dict(
                                {
                                    'validator_failed': ' 不是有效的邮箱地址'
                                }, **_default_error_messages),
                            help_text='登录名称', validate=_email_validator)
    password = fields.Str(required=True, allow_none=False,
                          error_messages=dict({'validator_failed': ' 必于大于6位'}, **_default_error_messages),
                          help_text="登录密码",
                          validate=_length_validator(6))

    def handle_error(self, error, data):
        print(error, data)


class PaginationParam(ma.Schema):
    current_page = fields.Int()
    page_size = fields.Int()


class ProductQueryParam(CurrencyPostSchema):
    pagination = fields.Nested(PaginationParam)
    last_id = fields.Str()
    max_size = fields.Int()
    title = fields.Str()


class HotProductParam(CurrencyPostSchema):
    max_count = fields.Int()

    category = fields.Function(deserialize=lambda obj: ProductCategory.get(ProductCategory.id == obj),
                               load_from='category_id')


class CheckoutParam(ma.Schema):
    currency = fields.Str(required=True, error_messages=_default_error_messages)
    fund_channel = fields.Str(required=True, error_messages=_default_error_messages)
    cart_items = fields.List(fields.Int, required=True, error_messages=_default_error_messages)
    notify_info = fields.Dict()


class CreateShopCartParam(ma.Schema):
    member = fields.Str(required=True, error_messages=_default_error_messages)
    cart_items = fields.List(fields.Int)
    items_from = fields.Str()


class UpdateShopCartSchema(ma.Schema):
    items = fields.List(fields.Nested(ShopCartItemSchema, only=('count', 'id', 'services')))


class ProductParam(ma.Schema):
    product = fields.Function(deserialize=lambda p: Product.get_or_none(Product.id == p), required=True,
                              error_messages=create_error_messages(validator_failed='商品不存在或已下架'),
                              validate=_none_validator)


class CurrencyQuerySchema(ma.Schema):
    currency = fields.Function(deserialize=lambda obj: Currency.get(Currency.id == obj), load_from='c')


class NewOfferParam(CurrencyPostSchema, ProductParam):
    price = fields.Number(required=True, error_messages=create_error_messages(
        validator_failed='金额无效', invalid="金额不是有效的数字"
    ), validate=_amount_validator)
    recommend = fields.Bool()
    inventory = fields.Dict()
    type = fields.Str()


class AccountHisFilterParam(PaginationParam):
    period = fields.Str()
    status = fields.Str()


account_history_filter_param = AccountHisFilterParam()

product_query_param = ProductQueryParam()
new_offer_param = NewOfferParam(strict=False)
checkout_param = CheckoutParam(strict=True)
hot_product_param = HotProductParam()
local_auth_schema = LocalAuthSchema(strict=True)
shop_cart_param = ShopCartSchema()
shop_cart_item_param = ShopCartItemSchema(strict=True)
currency_param = CurrencyQuerySchema()
update_schop_cart_param = UpdateShopCartSchema()
create_shop_cart_param = CreateShopCartParam()
pagination_param = PaginationParam()
